﻿// ------------------------------------------------------------------------
// 版权信息
// 版权归重庆虫儿飞科技有限公司所有。
// 所有权利保留。
// 官方网站：https://netokit.com
// 许可证信息
// Neto.Kit 项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。
// 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。
// 
// 使用条款
// 使用本代码应遵守相关法律法规和许可证的要求。
// 
// 免责声明
// 对于因使用本代码而产生的任何直接、间接、偶然、特殊或后果性损害，我们不承担任何责任。
// 
// 其他重要信息
// Neto.Kit 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。
// 有关 Neto.Kit 项目的其他详细信息，请参阅位于源代码树根目录中的 COPYRIGHT 和 DISCLAIMER 文件。
// 
// 更多信息
// 请访问 https://netokit.com 获取更多关于 Neto.Kit 项目的许可证和版权信息。
// ------------------------------------------------------------------------

using Microsoft.AspNetCore.Http;
using Neto.Core.CoreServices;
using Neto.Db.SqlSugar;
using Neto.Db.SqlSugar.Paged;
using Neto.Web;

namespace Neto.Application.Api;

/// <summary>
///     文件
/// </summary>
[Authorize] //jwt授权
[ApiDescriptionSettings("Api", Name = "SysFiles")]
//[MaApi(controller: "SysFiles", controllerDescription: "文件", PCode = "Api")]
[ApiArea()]
[PgApiController("文件管理服务", area: "Api", MenuPCode = "Sys_Setting")]
//[PgApiMenu("文件", "UrlKey_ApiSysFiles", "Api")]
//[Route("Api/[controller]/[action]")]
//[PgApiMenu("云存储", "file-manage_cloud", MenuPCode = "Sys_FileManage", Icon = "ic:outline-cloud", Sort = 1)]
//[PgApiMenu("自定义存储", "file-manage_customize", MenuPCode = "Sys_FileManage", Icon = "material-symbols:attach-file-rounded", Sort = 2)]
//[PgApiMenu("本地存储", "file-manage_local", MenuPCode = "Sys_FileManage", Icon = "clarity:server-line", Sort = 3)]
[PgApiMenu("文件管理", "sys-setting_file-manage", MenuPCode = "Sys_Setting",
    Icon = "material-symbols:folder-managed-outline-sharp", Sort = 1)]
public class ApiSysFilesService(
    ISqlSugarClient db,
    ISysFileService sysFileService
)
    : IDynamicApiController
{
    /// <summary>
    ///     上传图片并返回Fid
    /// </summary>
    /// <param name="file">文件</param>
    /// <returns></returns>
    [PgApiAction("上传图片到本地", MenuPCode = "Api_SysFiles_Menu_file-manage_local")]
    [OperationId(nameof(UploadImageLocal))]
    [HttpPost]
    public async Task<string> UploadImageLocal(IFormFile file)
    {
        var config = new ApiSysFilesUploadDto
        {
            Category = "image-default",
            File = file,
            FileStoLocType = FileStoLocType.本地,
            IsOpen = true
        };


        var result = await SaveFile(config);

        if (!result.Success) throw Oops.Oh("上传失败");

        return result.FId;
    }

    /// <summary>
    /// 上传文件并返回Id
    /// </summary>
    /// <param name="config">文件配置</param>
    /// <returns></returns>
    [PgApiAction("上传文件")]
    [OperationId(nameof(UploadFormReturnId))]
    [HttpPost]
    public async Task<long> UploadFormReturnId([FromForm] ApiSysFilesUploadDto config)
    {
        var result = await SaveFile(config);
        return result.Id;
    }

    /// <summary>
    ///     保存文件以及提交到数据库
    /// </summary>
    /// <param name="config"></param>
    /// <returns></returns>
    private async Task<WebUploadResult> SaveFile(ApiSysFilesUploadDto config)
    {
        if (string.IsNullOrWhiteSpace(config.Category)) config.Category = "default";
        var uploadConfig = new WebUploadConfig(config.Category, []);

        var result = await WebUpload.UploadFile(uploadConfig, config.File);

        if (result.Success)
        {
            //保存到数据库

            var sysFile = config.Adapt<SysFiles>();
            sysFile.Name = result.UploadFilename;
            sysFile.Extension = result.Extension;
            sysFile.Size = result.FileSize_Byte;
            sysFile.RelFileFloder = result.RelFileFloder;
            sysFile.FilePath = result.RelFilePath;
            sysFile.FId = result.FId;
            sysFile.ImgFilePathThumbnail = result.ThumbnailRelFileName;
            var Id = await db.InsertRsIdAsync(sysFile);
            result.Id = Id;
        }

        return result;
    }

    /// <summary>
    ///     获取文件
    /// </summary>
    /// <returns></returns>
    [Route("/f/{id}")]
    [HttpGet]
    [PgApiAction("获取文件")]
    public async Task<IActionResult> GetFile(string id) //要下载文件码
    {
        return await sysFileService.GetFile(id, false);
    }

    /// <summary>
    ///     获取缩略图
    /// </summary>
    /// <returns></returns>
    [Route("/f/t/{id}")]
    [HttpGet]
    [PgApiAction("获取缩略图")]
    public async Task<IActionResult> GetThumbnail(string id) //要下载文件码
    {
        return await sysFileService.GetFile(id, true);
    }

    /// <summary>
    ///     获取文件(开放权限)
    /// </summary>
    /// <returns></returns>
    [Route("/f/o/{id}")]
    [HttpGet]
    [AllowAnonymous]
    public async Task<IActionResult> GetOpenFile(string id) //要下载文件码
    {
        return await sysFileService.GetFile(id, false, true);
    }

    /// <summary>
    ///     获取缩略图
    /// </summary>
    /// <returns></returns>
    [Route("/f/o/t/{id}")]
    [HttpGet]
    [AllowAnonymous]
    public async Task<IActionResult> GetOpenThumbnail(string id) //要下载文件码
    {
        return await sysFileService.GetFile(id, true, true);
    }

    /// <summary>
    ///     更新一条
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [PgApiAction("更新一条")]
    [OperationId(nameof(Update))]
    [HttpPut]
    public async Task<bool> Update(ApiSysFilesInput input)
    {
        ////验证 父级下 唯一 Key是否存在
        //var isexit = await db.Queryable<SysFiles>().AnyAsync(o => o.PKey == input.PKey && o.Key == input.Key && o.Id != input.Id);
        //if (isexit)
        //{
        //    throw Oops.Bah("唯一标识Key不能重复");
        //}
        var dbentity = await db.Queryable<SysFiles>().With(SqlWith.Null).FirstAsync(o => o.Id == input.Id.Value);
        input.Adapt(dbentity);
        return await db.UpdateAsync(dbentity);
    }


    ///// <summary>
    ///// 删除一条
    ///// </summary>
    ///// <param name="id"></param>
    //[PgApiAction(name: "删除一条")]
    //[OperationId(nameof(Delete))]
    //public async Task<bool> Delete(long id)
    //{
    //    if (id <= 0) throw Oops.Bah("id不能为0");
    //    return  await db.DeleteByIdAsync<SysFiles>(id);
    //}

    ///// <summary>
    ///// 批量删除
    ///// </summary>
    ///// <param name="ids">需要删除的数据，多条以英文逗号隔开</param>
    //[PgApiAction(name: "批量删除")]
    //[OperationId(nameof(BatchDelete))]
    //public async Task<bool> BatchDelete(string ids)
    //{
    //    return await db.DeleteByIdsAsync<SysFiles>(ids);
    //}

    /// <summary>
    ///     假删除
    /// </summary>
    /// <param name="id"></param>
    [PgApiAction("假删除")]
    [OperationId(nameof(FakeDelete))]
    public async Task<bool> FakeDelete(long id)
    {
        return await db.FakeDeleteAsync<SysFiles>($"{id}");
    }

    /// <summary>
    ///     批量假删除
    /// </summary>
    /// <param name="ids">需要删除的数据，多条以英文逗号隔开</param>
    [PgApiAction("批量假删除")]
    [OperationId(nameof(BatchFakeDelete))]
    public async Task<bool> BatchFakeDelete(string ids)
    {
        return await db.FakeDeleteAsync<SysFiles>(ids);
    }


    /// <summary>
    ///     查询一条
    /// </summary>
    /// <param name="id"></param>
    [PgApiAction("查询一条")]
    [HttpPost]
    [OperationId(nameof(Get))]
    public async Task<ApiSysFilesOut> Get(long id)
    {
        /* 多表关联的一个写法，当然也可以用导航写法
         var query5 = await db.Queryable<SysFiles>()
           //.LeftJoin<Custom>   ((o, cus ) => o.CustomId == cus.Id)//多个条件用&&
           //.LeftJoin<OrderDetail> ((o, cus, oritem) => o.Id == oritem.OrderId)
           .Where(o => o.Id == id)
           .Select((o) => new ApiSysFilesOut {
                Id = o.Id.SelectAll(), //Id是o任意一个属性
                //CustomName = cus.Name,
            })
           .FirstAsync();
        */

        return await db.GetByIdAsync<SysFiles, ApiSysFilesOut>(id);
    }


    /// <summary>
    ///     分页查询
    /// </summary>
    /// <param name="searchQuery"></param>
    /// <returns></returns>
    [PgApiAction("分页查询")]
    [HttpPost]
    [OperationId(nameof(GetList))]
    public async Task<PagedList<ApiSysFilesOut>> GetList(ApiSysFilesQuery searchQuery)
    {
        var queryable = db.Queryable<SysFiles>();

        #region 筛选条件

        //开始日期
        if (searchQuery.StartDate.HasValue)
            queryable = queryable.Where(o => o.CreationTime >= searchQuery.StartDate.Value);
        //结束日期
        if (searchQuery.EndDate.HasValue)
            queryable = queryable.Where(o => o.CreationTime <= searchQuery.EndDate.ToDayEndTime());
        //关键词
        if (!string.IsNullOrWhiteSpace(searchQuery.KeyWords))
        {
            var kw = searchQuery.KeyWords?.Trim()?.ToLower() ?? "";
            queryable = queryable.Where(o => o.Name.Contains(kw));
        }

        #endregion

        queryable = queryable.OrderByDescending(o => o.Id);
        var pagelist = await queryable.Select(o => new ApiSysFilesOut
        {
            Id = o.Id.SelectAll(),

            #region 自定义

            //IsOpenName =  o.IsOpen?"是":"否"  ,//是否开放文件 
            //IsWwwrootName =  o.IsWwwroot?"是":"否"  ,//是否存在静态目录 
            //IsDeletedName =  o.IsDeleted?"是":"否"  ,//默认假删除 

            #endregion
        })
            .Mapper(src =>
            {
            })
            .ToPagedListAsync(searchQuery.PageIndex, searchQuery.PageSize);


        //var pagelist= await pageResult.ToPagedListAsync<SysFiles, ApiSysFilesOut>(searchQuery.PageIndex, searchQuery.PageSize);

        return pagelist;
    }

    /// <summary>
    ///     设置开放状态
    /// </summary>
    /// <param name="id"></param>
    /// <param name="state"></param>
    /// <returns></returns>
    [PgApiAction("设置开放状态")]
    [OperationId(nameof(SetIsOpen))]
    public async Task<bool> SetIsOpen(long id, bool state)
    {
        return await db.SetStateByIdAsync<SysFiles>(id, state, "IsOpen");
    }

    ///// <summary>
    ///// 设置状态
    ///// </summary>
    ///// <param name="id"></param>
    ///// <param name="state"></param>
    ///// <returns></returns>
    //[PgApiAction(name: "设置启用状态")]
    //[OperationId(nameof(SetIsEnable))]
    //public async Task<bool> SetIsEnable(long id, bool state)
    //{
    //    return await db.SetStateByIdAsync<SysFiles>(id, state, "IsEnable");
    //}

    #region 冗余方法

    ///// <summary>
    ///// 查询所有
    ///// </summary>
    ///// <returns></returns>
    //[PgApiAction(name: "查询所有")]
    //[OperationId(nameof(GetAll))]
    //public async Task<List<ApiSysFilesOut>> GetAll()
    //{
    //    return await db.GetListAsync<SysFiles, ApiSysFilesOut>();
    //}

    ///// <summary>
    ///// 获取下拉选项
    ///// </summary>
    ///// <returns></returns>
    //[PgApiAction(name: "获取下拉选项")]
    //[HttpPost]
    //[OperationId(nameof(GetSelectItems))]
    //public async Task<Dictionary<string, object>> GetSelectItems()
    //{
    //    var dics = await db.Queryable<SysFiles>().ToDictionaryAsync(o => o.Id, v => v.Title);
    //    return dics;
    //}

    #endregion
}